/**
* This file is part of programmer.
* Description: 
* If you use this code, please cite the respective publications as
* listed on the above website.
*
* programmer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* programmer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with programmer. If not, see <http://www.gnu.org/licenses/>.
*
* @file        simplifyPath.cpp.c
* @brief       Defines the 
* @author      Ziqiang Wang
* @email       1531651@tongji.edu.cn
* @date        2021/3/26
* @copyright   Copyright (c) 2021
*----------------------------------------------------------------------------*
*  Remark         : Description                                              *
*----------------------------------------------------------------------------*
*  Change History :                                                          *
*  <Date>     | <Version> | <Author>       | <Description>                   *
*----------------------------------------------------------------------------*
*  2021/3/26    | 1.0.0.0   | Ziqiang Wang   | Create file                     *
*----------------------------------------------------------------------------*
*                                                                            *
*/

#include "simplifyPath.h"


/*
给你一个字符串 path ，表示指向某一文件或目录的 Unix 风格 绝对路径 （以 '/' 开头），请你将其转化为更加简洁的规范路径。

在 Unix 风格的文件系统中，一个点（.）表示当前目录本身；此外，两个点 （..） 表示将目录切换到上一级（指向父目录）；两者都可以是复杂相对路径的组成部分。任意多个连续的斜杠（即，'//'）都被视为单个斜杠 '/' 。 对于此问题，任何其他格式的点（例如，'...'）均被视为文件/目录名称。

请注意，返回的 规范路径 必须遵循下述格式：

始终以斜杠 '/' 开头。
两个目录名之间必须只有一个斜杠 '/' 。
最后一个目录名（如果存在）不能 以 '/' 结尾。
此外，路径仅包含从根目录到目标文件或目录的路径上的目录（即，不含 '.' 或 '..'）。

返回简化后得到的 规范路径 。



示例 1：

输入：path = "/home/"
输出："/home"
解释：注意，最后一个目录名后面没有斜杠。

示例 2：

输入：path = "/../"
输出："/"
解释：从根目录向上一级是不可行的，因为根目录是你可以到达的最高级。

示例 3：

输入：path = "/home//foo/"
输出："/home/foo"
解释：在规范路径中，多个连续斜杠需要用一个斜杠替换。

示例 4：

输入：path = "/a/./b/../../c/"
输出："/c"



提示：

1 <= path.length <= 3000
path 由英文字母，数字，'.'，'/' 或 '_' 组成。
path 是一个有效的 Unix 风格绝对路径。

来源：力扣（LeetCode）
链接：https://leetcode-cn.com/problems/simplify-path
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。*/
#include <vector>
#include <cstdio>
#include <string>
#include <iostream>
#include <deque>
#include <stack>

using namespace std;

class Solution {
public:
    bool print = false;
    string FilterBar(const string& path) const
    {
        if (print) {
            std::cout << "\nori: " << path;
        }
        if (path.size() == 1) {
            return path;
        }
        stack<char> pathInverse;
        pathInverse.push(path[0]);
        for (auto &s : path) {
            if (pathInverse.top() == '/') {
                if (s == '/') {
                    continue;
                } else {
                    pathInverse.push(s);
                }
            } else {
                pathInverse.push(s);
            }
        }

        deque<char> resultDeque{};
        while (!pathInverse.empty()) {
            resultDeque.push_front(pathInverse.top());
            pathInverse.pop();
        }
        string filterBarResult{};
        for (auto &s : resultDeque) {
            filterBarResult.push_back(s);
        }

        if (filterBarResult[filterBarResult.size() - 1] == '/') {
            filterBarResult.pop_back();
        }
        return filterBarResult;
    }

    string simplifyPath(string path)
    {
        auto filterBarResult = FilterBar(path);
        vector<string> pathWithoutBar;
        string currentCmd{};
        for (int i = 0; i < filterBarResult.size(); ++i) {
            if (filterBarResult[i] == '/') {
                pathWithoutBar.push_back(currentCmd);
                currentCmd.clear();
                currentCmd.push_back(filterBarResult[i]);
            } else {
                currentCmd.push_back(filterBarResult[i]);
            }
        }

        pathWithoutBar.push_back(currentCmd);

        stack<string> pathResultStack;
        for (auto &x : pathWithoutBar) {
            if (x.empty()) {
                continue;
            }

            if (x.size() == 2 && x[1] == '.') { // 2
                continue;
            } else if (x.size() == 3 && x[1] == '.' && x[2] == '.') { // 3 2
                if (!pathResultStack.empty()) {
                    pathResultStack.pop();
                    if (print) {
                        std::cout << "\n pop stack seg: " << x;
                    }
                }
            } else {
                pathResultStack.push(x);
                if (print) {
                    std::cout << "\n push stack seg: " << x;
                }
            }
        }

        string result;
        while (!pathResultStack.empty()) {
            std::cout << "\n seg: " << pathResultStack.top();
            result.insert(0, pathResultStack.top());
            pathResultStack.pop();
        }

        if (result.empty()) {
            result.push_back('/');
        }
        if (print) {
            std::cout << "\nres: " << result;
        }
        return result;
    }
};